import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
public class Tank {
    public static final int SPEED_X = 5;
    public static final int SPEED_Y = 5;
    public static final int WIDTH = 30;
    public static final int HEIGHT = 30;

    private boolean alive = true;
    private int health = 100;
    private boolean isPlayer;

    private int x, y;
    private int prevX, prevY;

    private boolean movingLeft = false, movingUp = false, movingRight = false, movingDown = false;

    private Direction moveDirection = Direction.STOP;
    private Direction turretDirection = Direction.L;

    private BloodBar healthBar = new BloodBar();
    private TankClient gameClient;
    private static final Random rand = new Random();

    private int moveSteps = rand.nextInt(12) + 3;

    private static Toolkit toolkit = Toolkit.getDefaultToolkit();
    private static Image[] tankImgs;
    private static Map<String, Image> directionImageMap = new HashMap<>();
    private List<Wall> walls = new ArrayList<>();

    public void setWalls(List<Wall> walls) {
        this.walls = walls;
    }


    static {
        tankImgs = new Image[] {
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankL.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankLU.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankU.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankRU.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankR.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankRD.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankD.gif")),
                toolkit.getImage(Tank.class.getClassLoader().getResource("images/tankLD.gif"))
        };

        directionImageMap.put("L", tankImgs[0]);
        directionImageMap.put("LU", tankImgs[1]);
        directionImageMap.put("U", tankImgs[2]);
        directionImageMap.put("RU", tankImgs[3]);
        directionImageMap.put("R", tankImgs[4]);
        directionImageMap.put("RD", tankImgs[5]);
        directionImageMap.put("D", tankImgs[6]);
        directionImageMap.put("LD", tankImgs[7]);
    }

    public Tank(int x, int y, boolean isPlayer) {
        this.x = x;
        this.y = y;
        this.prevX = x;
        this.prevY = y;
        this.isPlayer = isPlayer;
    }

    public Tank(int x, int y, boolean isPlayer, Direction dir, TankClient client) {
        this(x, y, isPlayer);
        this.moveDirection = dir;
        this.gameClient = client;
    }

    public void draw(Graphics g) {
        if (!alive) {
            if (!isPlayer) {
                gameClient.tanks.remove(this);
            }
            return;
        }

        if (isPlayer) {
            healthBar.draw(g);
        }

        g.drawImage(directionImageMap.get(turretDirection.toString()), x, y, null);
        move();
    }

    private void move() {
        prevX = x;
        prevY = y;

        switch (moveDirection) {
            case L:  x -= SPEED_X; break;
            case LU: x -= SPEED_X; y -= SPEED_Y; break;
            case U:  y -= SPEED_Y; break;
            case RU: x += SPEED_X; y -= SPEED_Y; break;
            case R:  x += SPEED_X; break;
            case RD: x += SPEED_X; y += SPEED_Y; break;
            case D:  y += SPEED_Y; break;
            case LD: x -= SPEED_X; y += SPEED_Y; break;
            case STOP: break;
        }

        if (moveDirection != Direction.STOP) {
            turretDirection = moveDirection;
        }

        // 边界限制
        if (x < 0) x = 0;
        if (y < 30) y = 30;
        if (x + WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - WIDTH;
        if (y + HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - HEIGHT;

        // 敌方 AI 控制移动 + 开火
        if (!isPlayer) {
            if (moveSteps == 0) {
                moveSteps = rand.nextInt(12) + 3;
                moveDirection = Direction.values()[rand.nextInt(Direction.values().length)];
            }
            moveSteps--;

            if (rand.nextInt(40) > 38) {
                fire();
            }

        }
        for (Wall w : walls) {
            if (this.getBounds().intersects(w.getRect())) {
                // 发生碰撞：回退
                x = prevX;
                y = prevY;
                break;
            }
        }
    }

    private void stay() {
        x = prevX;
        y = prevY;
    }

    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_LEFT:  movingLeft = true; break;
            case KeyEvent.VK_UP:    movingUp = true; break;
            case KeyEvent.VK_RIGHT: movingRight = true; break;
            case KeyEvent.VK_DOWN:  movingDown = true; break;
            case KeyEvent.VK_F2:
                if (!alive) {
                    alive = true;
                    health = 100;
                }
                break;
            case KeyEvent.VK_Q:
                System.exit(0);
                break;
        }
        updateDirection();
    }

    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_LEFT:  movingLeft = false; break;
            case KeyEvent.VK_UP:    movingUp = false; break;
            case KeyEvent.VK_RIGHT: movingRight = false; break;
            case KeyEvent.VK_DOWN:  movingDown = false; break;
            case KeyEvent.VK_CONTROL: fire(); break;
            case KeyEvent.VK_A: superFire(); break;
        }
        updateDirection();
    }
    private void updateDirection() {
        if (movingLeft && !movingUp && !movingRight && !movingDown) moveDirection = Direction.L;
        else if (movingLeft && movingUp) moveDirection = Direction.LU;
        else if (!movingLeft && movingUp && !movingRight) moveDirection = Direction.U;
        else if (movingUp && movingRight) moveDirection = Direction.RU;
        else if (movingRight && !movingDown) moveDirection = Direction.R;
        else if (movingRight && movingDown) moveDirection = Direction.RD;
        else if (movingDown && !movingLeft) moveDirection = Direction.D;
        else if (movingDown && movingLeft) moveDirection = Direction.LD;
        else moveDirection = Direction.STOP;
    }

    public Missile fire() {
        if (!alive) return null;
        int missileX = x + WIDTH / 2 - Missile.WIDTH / 2;
        int missileY = y + HEIGHT / 2 - Missile.HEIGHT / 2;
        Missile m = new Missile(missileX, missileY, isPlayer, turretDirection, gameClient);
        gameClient.missiles.add(m);
        return m;
    }

    private void superFire() {
        for (Direction dir : Direction.values()) {
            if(dir!=Direction.STOP){
                fire(dir);
            }
        }
    }

    public Missile fire(Direction dir) {
        if (!alive) return null;
        int missileX = x + WIDTH / 2 - Missile.WIDTH / 2;
        int missileY = y + HEIGHT / 2 - Missile.HEIGHT / 2;
        Missile m = new Missile(missileX, missileY, isPlayer, dir, gameClient);
        gameClient.missiles.add(m);
        return m;
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, WIDTH, HEIGHT);
    }

    public boolean isAlive() {
        return alive;
    }

    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    public boolean isPlayerControlled() {
        return isPlayer;
    }

    public int getLife() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public boolean collidesWithWall(Wall wall) {
        if (alive && this.getBounds().intersects(wall.getRect())) {
            stay();
            return true;
        }
        return false;
    }

    public boolean collidesWithOtherTanks(List<Tank> tanks) {
        for (Tank other : tanks) {
            if (this != other && alive && other.isAlive() && this.getBounds().intersects(other.getBounds())) {
                this.stay();
                other.stay();
                return true;
            }
        }
        return false;
    }

    public boolean eat(Blood blood) {
        if (alive && blood.isLive() && this.getBounds().intersects(blood.getRect())) {
            this.health = 100;
            AudioUtil.playBloodSound();
            blood.setLive(false);
            return true;
        }
        return false;
    }

    private class BloodBar {
        public void draw(Graphics g) {
            Color prevColor = g.getColor();
            g.setColor(Color.RED);
            g.drawRect(x, y - 10, WIDTH, 10);
            int filledWidth = WIDTH * health / 100;
            g.fillRect(x, y - 10, filledWidth, 10);
            g.setColor(prevColor);
        }
    }
}
